<template>
  <div class="page-list">
    <div class="page-list-tabs">
      <slot name="tabs" :query="props.query" />
    </div>
    <!-- 搜索 -->
    <div class="page-list-search">
      <slot name="search" :query="props.query" :page="page" :sort="sort" :columns="columns" :hidden-columns="hiddenColumns" />
    </div>
    <slot name="table-before" :data="extentData" />
    <!-- 表格 -->
    <div class="page-list-table" v-loading="loading">
      <slot name="table" :data="data" :page="page" :hidden-columns="hiddenColumns" :sort="sort" />
    </div>
    <!-- 分页器 -->
    <div class="page-list-pagination">
      <slot name="pagination" :page="page" :total="total" />
    </div>

    <ElDrawer
      v-model="showDrawer"
      direction="rtl"
      size="75%"
      destroy-on-close
      :with-header="false"
      class="page-list-drawer"
    >
      <ElScrollbar height="100%">
        <slot name="drawer" :row="drawerRow" />
      </ElScrollbar>
    </ElDrawer>
  </div>
</template>

<script setup lang="ts">
import { withDefaults, ref, reactive, onMounted, defineExpose, provide } from 'vue'
import { useColumns } from '@/utils/columns'

interface Props {
  query: object;
  api: (params?: any) => Promise<any>;
  columns: Array<{ prop: string, label: string }>;
  autoFetch?: boolean;
}
const props = withDefaults(defineProps<Props>(), {
  query: () => ({}),
  api: () => Promise.resolve({ page: 1, size: 10, total: 0, data: [] }),
  columns: () => [],
  autoFetch: true
})

const loading = ref(false)
const data = ref<Array<any>>([])
const extentData = ref<any>()
const page = reactive({
  page: 1,
  size: 10
})
const sort = reactive({
  sidx: '',
  order: ''
})
const total = ref(0)
const selection = ref([])

const showDrawer = ref(false)
const drawerRow = ref()

provide('query', props.query)

// 获取数据
const getData = () => {
  const params = {
    page: {
      index: page.page,
      size: page.size
    },
    sort,
    condition: {
      ...props.query
    }
  }
  loading.value = true
  return props.api(params).then(res => {
    data.value = res.list || []
    total.value = res.totalCount || 0
    extentData.value = res.extentParams
  }).finally(() => {
    loading.value = false
  })
}

// 换页
const changePage = (change: { page?: number, size: number }) => {
  Object.assign(page, change)
  getData()
}

// 排序
const sortChange = ({ prop, order }) => {
  const map = {
    ascending: 'asc',
    descending: 'desc'
  }
  sort.order = map[order] || ''
  sort.sidx = prop
  getData()
}

// 刷新
const refresh = () => {
  page.page = 1
  getData()
}

// 新增页面
const addRow = async (dialog) => {
  if (typeof dialog === 'function') {
    await dialog()
  } else {
    await dialog.open()
  }
  getData()
}

// 编辑页面
const editRow = async (dialog, row) => {
  if (typeof dialog === 'function') {
    await dialog({ row })
  } else {
    await dialog.open({ row })
  }
  getData()
}

const batchDeleteRows = async (dialog) => {
  if (typeof dialog === 'function') {
    await dialog({ ids: selection.value.map(i => i.id), selection: selection.value })
  } else {
    await dialog.open({ ids: selection.value.map(i => i.id), selection: selection.value })
  }
  getData()
}

// 选择
const selectionChange = (sel) => {
  selection.value = sel || []
}

const openDrawer = (data = {}) => {
  showDrawer.value = true
  drawerRow.value = data
}

const closeDrawer = () => {
  showDrawer.value = false
}

// 挂在获取数据
onMounted(() => {
  if (props.autoFetch) {
    getData()
  }
})

// 隐藏列
const { hiddenColumns, changeColumn } = useColumns()

defineExpose({
  getData,
  changePage,
  refresh,
  addRow,
  editRow,
  sortChange,
  selectionChange,
  batchDeleteRows,
  openDrawer,
  closeDrawer,
  changeColumn
})
</script>

<style scoped lang="scss">
.page-list {
  padding: 12px;
  background: var(--el-color-white);

  &-table {
    margin-top: 10px;
  }
  &-pagination {
    display: flex;
    align-items: center;
    justify-content: flex-end;
  }

  :deep(.page-list-drawer .el-drawer__body) {
    padding: 0;
  }
}
</style>
